/**
 ******************************************************************************
 * @file           : heading_diff_ctrl_c.cpp
 * @author         : wangyingjie
 * @brief          : None
 * @attention      : None
 * @date           : 2025/5/23
 ******************************************************************************
 */

#include "heading_diff_ctrl_c.h"


//// 小船控制结构体
//typedef struct
//{
//    studio_pid heading_pid;  // 方位角PID控制器
//    studio_point_c target;   // 目标点
//    double base_throttle;    // 基础油门
//    double left_throttle;    // 左侧油门
//    double right_throttle;   // 右侧油门
//} diff_ctrl;

// 初始化小船控制器
void init_diff_ctrl(diff_ctrl *controller,
                          const studio_point_c *target,
                          double base_throttle,  // 输入范围0~1.0
                          double Kp,
                          double Ki,
                          double Kd)
{
    init_pid(&controller->heading_pid, 0, 0, Kp, Ki, Kd, 1.0, 0.3);
    controller->target = *target;
    controller->base_throttle = base_throttle;
    controller->left_throttle = base_throttle;
    controller->right_throttle = base_throttle;
}

void reset_diff_ctrl_goal(diff_ctrl* controller, const studio_point_c* target)
{
    controller->target = *target;
    set_goal(&controller->heading_pid, 0);
}

// 正确计算最短路径误差（返回-180~180°）
double calculate_heading_error(double target_deg, double current_deg)
{
    double error = target_deg - current_deg;
    error = fmod(error + 360.0, 360.0);  // 转0~360°
    if (error > 180.0)
    {
        error -= 360.0;
    }
    return error;
}

double update_boat(diff_ctrl *controller, const studio_point_c *current_pos, double current_heading_deg)
{
    // 1. 计算目标方位角（确保函数正确）
    const double target_deg = azimuth_angle_gcs_c(current_pos, &controller->target);

    // 2. 计算最短路径误差
    double error = calculate_heading_error(target_deg, current_heading_deg);
    double steer = 0.0;

    // 3. PID控制
    if (fabs(error) > 1.0)  // 仅当误差超过1度时进行纠偏
    {
        set_goal(&controller->heading_pid, 0);
        steer = compute_pid(&controller->heading_pid, error);
    }
    else
    {

    }

    // 4. 差速控制（关键修正）
    controller->left_throttle = controller->base_throttle - steer;
    controller->right_throttle = controller->base_throttle + steer;

    // 5. 限幅保护
    controller->left_throttle = fmax(0.0, fmin(1.0, controller->left_throttle));
    controller->right_throttle = fmax(0.0, fmin(1.0, controller->right_throttle));

    return distance_squared_gcs_c(current_pos, &controller->target);
}

void simulate_movement(studio_point_c *current_pos, double *current_heading, double left_throttle, double right_throttle)
{
    const double dt = 0.1;         // 时间间隔（秒）
    const double max_speed = 2;  // 最大速度（米/秒）
    const double turn_rate = 40;  // 转向速率（度/秒 per 差速百分比）

    // 保存原始位置用于计算位移
    const studio_point_c original_pos = *current_pos;

    // 1. 计算航向变化 ---------------------------------------------
    double steer_diff = left_throttle - right_throttle;
    *current_heading += turn_rate * steer_diff * dt;
    *current_heading = fmod(*current_heading + 360.0, 360.0);

    // 2. 计算位移量（米）------------------------------------------
    double avg_throttle = (left_throttle + right_throttle) / 2.0;
    double speed = max_speed * avg_throttle;

    // 将航向角转换为弧度
    double radian = *current_heading * AO_M_PI / 180.0;

    // 计算东向和北向位移（单位：米）
    const double delta_east = speed * sin(radian) * dt;   // 东向位移（+东/-西）
    const double delta_north = speed * cos(radian) * dt;  // 北向位移（+北/-南）

    // 3. 通过投影转换更新位置 -------------------------------------
    *current_pos = lonlat_move_by(&original_pos, delta_east, delta_north);
}


